#pragma once

#include <iostream>
#include "HandlerRequest.hpp"
#include "LogMessage.hpp"
#include "TcpServer.hpp"

// 普通套接字的读写错误事件的处理方式
class EventHandler
{
public:
    //ET工作模式下，读采用非阻塞轮询方式读取
    static void Reader(Connect* conn)
    {
        if (conn == nullptr)
        {
            lg.LogMessage(Warning, "In Reader, conn is nullptr");
            return;
        }

        while (true)
        {
            char buffer[1024];
            int n = read(conn->GetSock()->GetSockfd(), buffer, sizeof(buffer) - 1);
            if (n > 0)
            {
                //读取成功，添加到接受缓冲区当中
                buffer[n] = 0;
                conn->GetInBuffer() += buffer;
            }
            else if (n == 0)
            {
                //对端关闭连接，直接按读取失败处理即可
                conn->_excepter(conn);
                return;
            }
            else
            {
                if (errno == EAGAIN) //接受缓冲区为空，数据读取完毕了
                    break;
                else if (errno == EINTR) //被信号终端了，重新执行
                    continue;
                else  //执行出错
                {
                    lg.LogMessage(Warning, "read error");
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        HandlerMessage::HandlerRequest(conn);
    }

    static void Writer(Connect* conn)
    {
        if (conn == nullptr)
        {
            lg.LogMessage(Warning, "In Writer, conn is nullptr");
            return;
        }

        std::string& outbuffer = conn->GetOutBuffer();
        while (!outbuffer.empty())
        {
            ssize_t n = write(conn->GetSock()->GetSockfd(), outbuffer.c_str(), outbuffer.size());
            if (n >= 0)
            {
                outbuffer.erase(0, n);
                if (outbuffer.empty())
                    break;
            }
            else
            {
                if (errno == EAGAIN) //发送缓冲区已经满了，不能再发了
                    break;
                else if (errno == EINTR) //被信号中断了，重新发送
                    continue;
                else 
                {
                    lg.LogMessage(Warning, "write error");
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        //走到这里，有两种情况
        //1. outbuffer中的数据全部读取完毕 -- 关闭对读事件的关心
        if (outbuffer.empty())
            conn->_Rector->SetReadAndWrite(conn->GetSock()->GetSockfd(), true, false);
        //2. send的发送缓冲区被写满，短时间内无法再send -- 开启对读事件的关心
        else 
            conn->_Rector->SetReadAndWrite(conn->GetSock()->GetSockfd(), true, true);
    }

    static void Excepter(Connect* conn)
    {
        if (conn == nullptr)
        {
            lg.LogMessage(Warning, "In Excepter, conn is nullptr");
            return;
        }

        // 将conn中的sock从epoll中移除
        conn->_Rector->DelConnect(conn);
        close(conn->GetSock()->GetSockfd());

        // 将conn对应的sock关闭
        close(conn->GetSock()->GetSockfd());

        // 将sock释放掉
        delete conn->GetSock();

        // 将conn释放
        delete conn;
    }
};